#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>

#define MAXSIZE 256
#define INERROR -1
#define INPT 0
#define INADD 1
#define INFLUSH 2
#define INKILL 3
#define INSTOP 4

#define TRUE 0
#define FALSE 1

/*STRUCTURE DU TLB*/

struct _tlb_entry
{
    int page_num;
    int frame_num;
};

struct _tlb_table
{
    int entry_num;
    struct _tlb_entry *tbe;
};

/*STRUCTURE TABLE DES CADRES*/

struct _frame_table_entry
{
    unsigned char is_bound ;
    int proc_id ;
};

struct _frame_table {
    int frame_num ;
    struct _frame_table_entry *fte;
};

/*STRUCTURE TABLE DES PAGES*/

struct _page_table_entry
{
    int frame_num ;
    unsigned char dirty ;
    unsigned char valid ;
};

struct _page_table
{
    int page_num ;
    int process_num ;
    struct _page_table_entry *pte;
};


typedef struct _tlb_table TLB_table;
typedef struct _page_table Page_table ;
typedef struct _frame_table Frame_table ;


/*DECODER STDIN*/

static int read_and_parse(FILE *stream, int *outval1, int *outval2)
{
    char buffer[MAXSIZE];
    char lasts[MAXSIZE], *pt;
    char *argv[3];
    int argc;

    if(fgets(buffer, MAXSIZE, stream) == NULL) {
        if(feof(stream)){
            fprintf(stderr, "Fin de stdin atteinte! \n");
            return -1;
        } else if(ferror(stream)) {
            fprintf(stderr, "Erreur sur stdin!\n");
            return -1;
        }
    }

    /*lire les arguments*/

    pt = lasts;
    argc = 0;

    if((argv[argc++] = strtok_r(buffer," \t",&pt)) == NULL) {
        return INERROR;
    }

    while( (argv[argc] = strtok_r(NULL," \t",&pt)) != NULL ) {
        if(++argc >=3 ) break;
    }

   /*decoder les commandes*/

    if(!strncmp(argv[0],"PT",2) && argc == 2){
        *outval1 = atoi(argv[1]);
        return INPT;
    } else if(!strncmp(argv[0],"ADD",3) && argc == 3) {
        *outval1 = atoi(argv[1]);
        *outval2 = atoi(argv[2]);
        return INADD;
    } else if(!strncmp(argv[0],"FLUSH",5)) {
        return INFLUSH;
    } else if(!strncmp(argv[0],"KILL",4)) {
        return INKILL;
    }
    return INERROR;
}

static void init_surv(fd_set *s, struct timeval *t)
{
    FD_ZERO(s);
    FD_SET(fileno(stdin) ,s);
    t->tv_sec = 3;
    t->tv_usec = 0;
    return;
}

static void flush_tlb(TLB_table *tlb, int cadre_max)
{
    int i;

    tlb->entry_num = cadre_max;
    tlb->tbe = malloc(cadre_max*sizeof(int));

    for(i = 0; i < cadre_max; i++) {
        tlb->tbe[i].page_num = -1;
        tlb->tbe[i].frame_num = -1;
    }
}

static int pt_tlb(TLB_table tlb, int page_num)
{
    int i;

    for(i = 0; i < tlb.entry_num; i++)
    {
        if(tlb.tbe[i].page_num == page_num)
            return tlb.tbe[i].frame_num;
    }

    return -1;
}

/* Cherche la premiere entree libre du TLB
 */
int cherche_entree(TLB_table *tlb)
{
    int i;

    for(i = 0; i < tlb->entry_num; i++)
    {
        if(tlb->tbe[i].frame_num == -1)
        {
            return i;
        }
    }

    return -1;
}

/* Lorsque une entree du TLB est libre
 * une association entre n et k est fait
 */
int add_tlb(TLB_table *tlb, int page_num, int frame_num)
{
    int entry;
    entry = cherche_entree(tlb);
    if(entry != -1)
    {
        tlb->tbe[entry].page_num = page_num;
        tlb->tbe[entry].frame_num = frame_num;

        return 0;
    }

    return -1;
}

void affiche(TLB_table tlb)
{
    int i;
    for(i = 0; i<tlb.entry_num; i++)
    {
        printf("%d TLB FRAME NUM \n", tlb.tbe[i].frame_num);
        printf("%d TLB PAGE NUM \n", tlb.tbe[i].page_num);
    }
}

int main(int argc, char *argv[])
{
    fd_set wt;

    struct timeval timeout;
    int cadre_max;
    int page_max;
    int state;
    int retval;
    int outval1;
    int outval2;

    TLB_table tlb;

    if(argc != 3){
        fprintf(stderr,"%s <page> <cadre>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    page_max = atoi(argv[1]);
    cadre_max = atoi(argv[2]);

    if(page_max <= 1){
        page_max = 2;
    }

    if(cadre_max <= 1){
        cadre_max = 2;
    }
    flush_tlb(&tlb, cadre_max);

    state = INSTOP;
    init_surv(&wt,&timeout);

    while(1)
    {
        select(fileno(stdin)+1,&wt,NULL,NULL,&timeout);
        retval = state;

        if(FD_ISSET(fileno(stdin),&wt)){
            retval = read_and_parse(stdin, &outval1, &outval2);
            if(retval < 0){
                exit(EXIT_FAILURE);
            }
        }

        if(retval == INPT)
        {
            fprintf(stdout,"%d\n",pt_tlb(tlb, outval1));
            fflush(stdout);
        }
        else if(retval == INADD)
        {
            if(add_tlb(&tlb,outval1,outval2) == TRUE)
            {
                fprintf(stdout,"OK\n");
                fflush(stdout);
            }
            else
            {
                fprintf(stdout,"%d\n",-1);
                fflush(stdout);
            }
        }
        else if(retval == INFLUSH)
        {
           flush_tlb(&tlb,cadre_max);
           fprintf(stdout,"OK\n");
           fflush(stdout);
        }
        else if(retval == INKILL)
        {
            exit(EXIT_SUCCESS);
        }

        state = INSTOP;
        init_surv#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/select.h>

#define MAXSIZE 256
#define INERROR -1
#define INPT 0
#define INADD 1
#define INFLUSH 2
#define INKILL 3
#define INSTOP 4

#define TRUE 0
#define FALSE 1

/*STRUCTURE DU TLB*/

struct _tlb_entry
{
    int page_num;
    int frame_num;
};

struct _tlb_table
{
    int entry_num;
    struct _tlb_entry *tbe;
};

/*STRUCTURE TABLE DES CADRES*/

struct _frame_table_entry
{
    unsigned char is_bound ;
    int proc_id ;
};

struct _frame_table {
    int frame_num ;
    struct _frame_table_entry *fte;
};

/*STRUCTURE TABLE DES PAGES*/

struct _page_table_entry
{
    int frame_num ;
    unsigned char dirty ;
    unsigned char valid ;
};

struct _page_table
{
    int page_num ;
    int process_num ;
    struct _page_table_entry *pte;
};


typedef struct _tlb_table TLB_table;
typedef struct _page_table Page_table ;
typedef struct _frame_table Frame_table ;


/*DECODER STDIN*/

static int read_and_parse(FILE *stream, int *outval1, int *outval2)
{
    char buffer[MAXSIZE];
    char lasts[MAXSIZE], *pt;
    char *argv[3];
    int argc;

    if(fgets(buffer, MAXSIZE, stream) == NULL) {
        if(feof(stream)){
            fprintf(stderr, "Fin de stdin atteinte! \n");
            return -1;
        } else if(ferror(stream)) {
            fprintf(stderr, "Erreur sur stdin!\n");
            return -1;
        }
    }

    /*lire les arguments*/

    pt = lasts;
    argc = 0;

    if((argv[argc++] = strtok_r(buffer," \t",&pt)) == NULL) {
        return INERROR;
    }

    while( (argv[argc] = strtok_r(NULL," \t",&pt)) != NULL ) {
        if(++argc >=3 ) break;
    }

   /*decoder les commandes*/

    if(!strncmp(argv[0],"PT",2) && argc == 2){
        *outval1 = atoi(argv[1]);
        return INPT;
    } else if(!strncmp(argv[0],"ADD",3) && argc == 3) {
        *outval1 = atoi(argv[1]);
        *outval2 = atoi(argv[2]);
        return INADD;
    } else if(!strncmp(argv[0],"FLUSH",5)) {
        return INFLUSH;
    } else if(!strncmp(argv[0],"KILL",4)) {
        return INKILL;
    }
    return INERROR;
}

static void init_surv(fd_set *s, struct timeval *t)
{
    FD_ZERO(s);
    FD_SET(fileno(stdin) ,s);
    t->tv_sec = 3;
    t->tv_usec = 0;
    return;
}

static void flush_tlb(TLB_table *tlb, int cadre_max)
{
    int i;

    tlb->entry_num = cadre_max;
    tlb->tbe = malloc(cadre_max*sizeof(int));

    for(i = 0; i < cadre_max; i++) {
        tlb->tbe[i].page_num = -1;
        tlb->tbe[i].frame_num = -1;
    }
}

static int pt_tlb(TLB_table tlb, int page_num)
{
    int i;

    for(i = 0; i < tlb.entry_num; i++)
    {
        if(tlb.tbe[i].page_num == page_num)
            return tlb.tbe[i].frame_num;
    }

    return -1;
}

/* Cherche la premiere entree libre du TLB
 */
int cherche_entree(TLB_table *tlb){
    int i;

    for(i = 0; i < tlb->entry_num; i++)
    {
        if(tlb->tbe[i].frame_num == -1)
        {
            return i;
        }
    }

    return -1;
}

/* Lorsque une entree du TLB est libre
 * une association entre n et k est fait
 */
int add_tlb(TLB_table *tlb, int page_num, int frame_num){
    int entry;
    entry = cherche_entree(tlb);
    if(entry != -1)
    {
        tlb->tbe[entry].page_num = page_num;
        tlb->tbe[entry].frame_num = frame_num;

        return 0;
    }

    return -1;
}

void affiche(TLB_table tlb)
{
    int i;
    for(i = 0; i<tlb.entry_num; i++)
    {
        printf("%d TLB FRAME NUM \n", tlb.tbe[i].frame_num);
        printf("%d TLB PAGE NUM \n", tlb.tbe[i].page_num);
    }
}

int main(int argc, char *argv[])
{
    fd_set wt;

    struct timeval timeout;
    int cadre_max;
    int page_max;
    int state;
    int retval;
    int outval1;
    int outval2;

    TLB_table tlb;

    if(argc != 3){
        fprintf(stderr,"%s <page> <cadre>\n", argv[0]);
        exit(EXIT_FAILURE);
    }

    page_max = atoi(argv[1]);
    cadre_max = atoi(argv[2]);

    if(page_max <= 1){
        page_max = 2;
    }

    if(cadre_max <= 1){
        cadre_max = 2;
    }
    flush_tlb(&tlb, cadre_max);

    state = INSTOP;
    init_surv(&wt,&timeout);

    while(1)
    {
        select(fileno(stdin)+1,&wt,NULL,NULL,&timeout);
        retval = state;

        if(FD_ISSET(fileno(stdin),&wt)){
            retval = read_and_parse(stdin, &outval1, &outval2);
            if(retval < 0){
                exit(EXIT_FAILURE);
            }
        }

        if(retval == INPT)
        {
            fprintf(stdout,"%d\n",pt_tlb(tlb, outval1));
            fflush(stdout);
        }
        else if(retval == INADD)
        {
            if(add_tlb(&tlb,outval1,outval2) == TRUE)
            {
                fprintf(stdout,"OK\n");
                fflush(stdout);
            }
            else
            {
                fprintf(stdout,"%d\n",-1);
                fflush(stdout);
            }
        }
        else if(retval == INFLUSH)
        {
           flush_tlb(&tlb,cadre_max);
           fprintf(stdout,"OK\n");
           fflush(stdout);
        }
        else if(retval == INKILL)
        {
            exit(EXIT_SUCCESS);
        }

        state = INSTOP;
        init_surv(&wt,&timeout);
    }

    exit(EXIT_FAILURE);

}


(&wt,&timeout);
    }

    exit(EXIT_FAILURE);

}



